package org.tomcat.unit501;

import javax.servlet.Servlet;
import javax.servlet.ServletException;
import java.io.IOException;
import java.net.URLClassLoader;

public class SimpleWrapper implements Wrapper, Contained, Container {

    private Loader loader;

    protected Container parent = null;

    private String servletClass = null;

    private Servlet instance = null;

    private SimplePipeline pipeline = new SimplePipeline(this);

    public SimpleWrapper() {
        SimpleWrapperValve valve = new SimpleWrapperValve();
        valve.setContainer(this);
        pipeline.setBasic(valve);
    }

    public synchronized void setLoader(Loader loader) {
        Loader oldLoader = this.loader;
        if (oldLoader == loader)
            return;
        this.loader = loader;
    }

    @Override
    public void addChild(Container child) {

    }

    @Override
    public void removeChild(Container child) {

    }

    @Override
    public Container findChild(String name) {
        return null;
    }

    @Override
    public Container[] findChildren() {
        return new Container[0];
    }

    @Override
    public void invoke(Request request, Response response) throws IOException, ServletException {
        this.pipeline.invoke(request, response);
    }

    @Override
    public Loader getLoader() {
        if (loader != null) {
            return (loader);
        }
        if (parent != null) {
            return parent.getLoader();
        }
        return null;
    }

    public void addValve(Valve valve) {
        ((Contained)valve).setContainer(this);
        this.pipeline.addValve(valve);
    }

    @Override
    public Servlet allocate() throws ServletException {
        if (instance == null) {
            synchronized (this) {
                if (instance == null) {
                    try {
                        instance = loadServlet();
                    } catch (ServletException e) {
                        throw e;
                    } catch (Throwable e) {
                        throw new ServletException("allocate servlet class error.");
                    }
                }
            }
        }
        return instance;
    }

    public synchronized Servlet loadServlet() throws ServletException {
        ClassLoader classLoader = this.loader.getClassLoader();
        try {
            Class clazz = classLoader.loadClass(this.servletClass);
            return (Servlet)clazz.newInstance();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    @Override
    public void load() throws ServletException {

    }

    @Override
    public void setServletClass(String servletClass) {
        this.servletClass = servletClass;
    }

    @Override
    public String getServletClass() {
        return this.servletClass;
    }

    @Override
    public Container getContainer() {
        return null;
    }

    @Override
    public void setContainer(Container container) {

    }
}
